import pandas as pd
from sqlalchemy import create_engine, Column, Integer, String, MetaData, ForeignKey, and_, or_

'''数据库操作方法封装'''
'''①存数：插入数据'''
#df是你的dataframe
#session是创建的回话
#classname是类名（类名与表名相同），对不同的表插入数据，修改classname即可
def mydfinsert(df,session,classname):
    # 转换 DataFrame 为列表（字典的列表）
    df = df.to_dict(orient='records')
    # 批量插入
    objects = [classname(**eachline) for eachline in df]
    #注意如果没有插入正确的数据类型，可以轻易转化的就不会报错，比如对String(10)插入2，比如对datetime.now()插入'2023-12-10 16:10:00'，但是对datetime.now()插入'2023-12-10 161000'就会报错了
    session.add_all(objects) #add_all()换成bulk_save_objects()也是一样的
    session.commit()
    # 关闭会话
    session.close()


'''②存数：全表更新数据'''
def mydfallupdate(df,session,classname):
    # 删除原有数据
    session.query(classname).delete()
    # 转换 DataFrame 为列表（字典的列表）
    df = df.to_dict(orient='records')
    # 批量插入
    objects = [classname(**eachline) for eachline in df]
    session.add_all(objects)
    session.commit()
    # 关闭会话
    session.close()


'''③存数：若某字段取某值在数据库中有就更新数据（id会自动更新），若没有才插入数据'''
#unique_column是表的唯一键列表
def mydfmerge(df,session,classname,unique_column):
    columns=df.columns
    df = df.to_dict(orient='records')
    feiunique_column = [item for item in columns if item not in unique_column and item!='id']
    # 循环遍历数据
    for data in df:
        unique_value = [data[name] for name in unique_column]
        feiunique_value = [data[name] for name in feiunique_column]
        existing_record = session.query(classname).filter(
            and_(*[getattr(classname, column) == value for column, value in zip(unique_column, unique_value)])).first()
        if existing_record:
            # 定义要更新的字段名列表
            update_fields = feiunique_column
            # 定义新值列表
            new_values = feiunique_value
            # 使用 zip() 函数将两个列表打包成字典
            update_data = dict(zip(update_fields, new_values))
            session.query(classname).filter(
            and_(*[getattr(classname, column) == value for column, value in zip(unique_column, unique_value)])).update(update_data)
        else:
            session.add(classname(**data))
    session.commit()
    session.close()

